package deng.spring.userwebapp.services.spring;

import java.util.List;

import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;

import deng.spring.userwebapp.dal.entities.User;
import deng.spring.userwebapp.services.PasswordNotMatchedException;
import deng.spring.userwebapp.services.UserService;
import deng.spring.userwebapp.services.UsernameNotFoundException;

public class HibernateTemplateUserService extends AbstractHibernateCrudDao<User, Long> implements UserService {

	@Override
	public User authenticate(String username, String password)
			throws UsernameNotFoundException, PasswordNotMatchedException {
		
		User exampleEntity = new User();
		exampleEntity.setUsername(username);

		HibernateTemplate ht = getHibernateTemplate();
		List<?> userList = ht.findByExample(exampleEntity);
		if (userList.size() == 0) {
			throw new UsernameNotFoundException("Username: " + username);
		}
		User user = (User)userList.get(0);
		String userPassword = user.getPassword();
		if (userPassword != null && !userPassword.equals(password)) {
			throw new PasswordNotMatchedException("Password not matched for username: " + username);
		}
		
		return user;
	}

	@Override
	public int getUserCount() {
		// Returned Object type should be Long
		Object result = getHibernateTemplate().find("select count(e) from User e").get(0);
		return ((Number)result).intValue();
	}

	@Override
	public List<User> getUsers(final int firstResult, final int maxResult) {
		List<?> result = getHibernateTemplate().executeFind(new HibernateCallback<List<?>>() {
			@Override
			public List<?> doInHibernate(Session session) {
				return session.createQuery("from User e order by e.username")
					.setFirstResult(firstResult)
					.setMaxResults(maxResult)
					.list();
			}
		});
		@SuppressWarnings("unchecked")
		List<User> users = (List<User>)result;
		return users;
	}

	@Override
	public boolean usernameExists(String username) {
		List<?> result = getHibernateTemplate()
			.findByNamedParam("select count(*) from User e where e.username = :username", "username", username);
		Object countObject = result.get(0);
		return ((Number)countObject).intValue() == 1;
	}

}
